package db

import (
	"World/common"
	"World/common/logger"
	"World/redis"
	"encoding/json"
	"strconv"
	"sync"
	"time"
)

type UserDeviceInfo struct {
	Uuid           int32
	Device_uuid    string
	Create_time    int32
	Last_logintime int32
	Login_type     int32
	Token          string
}

type UserBaseInfo struct {
	Uuid        int32
	User_star   int32 //星星
	User_dimond int32 //美钞
	User_tili   int32 //体力
	Plan_num    int32 //飞机数量
	Boom_num    int32 //飞机数量
	Rainbow_num int32 //飞机数量
	Cur_level   int32 //飞机数量
	Sync_id     int64 //同步包id
}

//dtb_user_signdata
type UserSignData struct {
	Uuid          int32
	Sign_day      int32
	Is_signed     int32
	Sign_state    int32
	Last_signtime int32
}

func GetUuid(deviceuuid string) (int, error) {

	// *******************************
	if redis.GetRedisIsOpen() {
		baseinfo := new(UserDeviceInfo)
		val, err := redis.GetRedisClient().HGet(redis.WD_REDIS_USER_DEVICEINFO, deviceuuid)
		if err != nil {
			logger.Error("GetUuid failed err=%v", err)
			return 0, err
		}
		err = json.Unmarshal([]byte(val), baseinfo)
		if err != nil {
			logger.Error("GetUuid json failed err=%v", err)
			return 0, err
		}

		return int(baseinfo.Uuid), nil
	}
	// *******************************

	uuid := 0
	row := m_game_db.QueryRow("select uuid from dtb_user_deviceinfo where device_uuid = ?", deviceuuid)

	err := row.Scan(&uuid)

	if err != nil {
		logger.Info("GetUuid error:%v", err)
		return 0, err
	}

	return uuid, nil
}

func UpdateLogin(uuid int) error {
	nowt := time.Now().Unix()

	// *******************************
	if redis.GetRedisIsOpen() {

		baseinfo := new(UserDeviceInfo)
		val, err := redis.GetRedisClient().HGet(redis.WD_REDIS_USER_DEVICEINFO, strconv.Itoa(uuid))
		if err != nil {
			logger.Error("UpdateLogin failed err=%v", err)
			return err
		}
		err = json.Unmarshal([]byte(val), baseinfo)
		if err != nil {
			logger.Error("UpdateLogin json failed err=%v", err)
			return err
		}

		baseinfo.Last_logintime = int32(nowt)

		newval, err := json.Marshal(baseinfo)
		if err != nil {
			logger.Error("UpdateLogin err=%v", err)
			return err
		}

		err = redis.GetRedisClient().HSet(redis.WD_REDIS_USER_DEVICEINFO, strconv.Itoa(int(uuid)), string(newval))

		if err != nil {
			logger.Error("UpdateLogin err=%v", err)
			return err
		}
		return nil
	}
	// *******************************

	_, err := m_game_db.Exec("update dtb_user_deviceinfo set last_logintime= ? where uuid=?", nowt, uuid)
	if err != nil {
		logger.Info("Register error:%v", err)
		return err
	}

	return nil
}

func Register(deviceuuid string) (int, error) {
	nowt := time.Now().Unix()

	// *******************************
	if redis.GetRedisIsOpen() {
		uuid, err := redis.GetRedisClient().Incr(redis.WD_REDIS_USER_UUIDKEY)
		if err != nil {
			logger.Error("Register failed err=%v", err)
			return 0, err
		}
		baseinfo := new(UserDeviceInfo)

		baseinfo.Last_logintime = int32(nowt)
		baseinfo.Create_time = int32(nowt)
		baseinfo.Uuid = int32(uuid)
		baseinfo.Device_uuid = deviceuuid
		baseinfo.Token = ""

		newval, err := json.Marshal(baseinfo)
		if err != nil {
			logger.Error("Register err=%v", err)
			return 0, err
		}

		err = redis.GetRedisClient().HSet(redis.WD_REDIS_USER_DEVICEINFO, deviceuuid, string(newval))
		err = redis.GetRedisClient().HSet(redis.GS_USERDEVICE_INFO, strconv.Itoa(int(uuid)), string(newval))

		if err != nil {
			logger.Error("Register err=%v", err)
			return 0, err
		}

		//插入玩家主表
		uinfo := new(UserBaseInfo)
		uinfo.Uuid = int32(uuid)
		uinfo.User_star = 100
		uinfo.Sync_id = 0
		uinfo.User_dimond = 0
		uinfo.Rainbow_num = 5
		uinfo.Boom_num = 5
		uinfo.Plan_num = 5
		uinfo.Cur_level = 100000
		uinfo.User_tili = 5
		uval, err := json.Marshal(uinfo)
		if err != nil {
			logger.Error("Register err=%v", err)
			return 0, err
		}

		err = redis.GetRedisClient().HSet(redis.GS_USERBASE_INFO, strconv.Itoa(int(uuid)), string(uval))

		if err != nil {
			logger.Error("Register err=%v", err)
			return 0, err
		}

		sinfo := new(UserSignData)
		sinfo.Uuid = int32(uuid)
		sinfo.Last_signtime = int32(nowt)
		sval, err := json.Marshal(sinfo)
		if err != nil {
			logger.Error("Register err=%v", err)
			return 0, err
		}
		err = redis.GetRedisClient().HSet(redis.GS_USERSIGN_DATA, strconv.Itoa(int(uuid)), string(sval))

		if err != nil {
			logger.Error("Register err=%v", err)
			return 0, err
		}

		return int(uuid), nil

	}
	// *******************************

	//插入登录表
	_, err := m_game_db.Exec("insert into dtb_user_deviceinfo (device_uuid, create_time,last_logintime,login_token) values(?, ?,?,?)", deviceuuid, nowt, nowt, "")
	if err != nil {
		return 0, err
	}

	uuid := 0
	row := m_game_db.QueryRow("select uuid from dtb_user_deviceinfo where device_uuid = ?", deviceuuid)

	err = row.Scan(&uuid)
	if err != nil {
		logger.Info("Register error:%v", err)
		return 0, err
	}

	//插入玩家主表基础数据
	_, err = m_game_db.Exec("insert into dtb_user_main (uuid, user_data) values(?, ?)", uuid, "")
	if err != nil {
		logger.Info("Register error:%v", err)
		return 0, err
	}

	//初始化玩家签到数据
	_, err = m_game_db.Exec("insert into dtb_user_signdata(uuid,last_signtime) values(?,?)", uuid, nowt)
	if err != nil {
		logger.Info("Register error:%v", err)
		return 0, err
	}

	return uuid, nil
}

func LoadPlayerFromDB(uid int) (*common.GamePlayer, error) {
	//	cmd := `select  COALESCE(id,0), COALESCE(mobile,''), COALESCE(passwd,''), COALESCE(avatar,''), COALESCE(avatar_thumb,''),
	//                COALESCE(nick_name,''), COALESCE(gender,0), COALESCE(user_marks,''), COALESCE(diamond_num,0), COALESCE(user_gold,0),
	//                COALESCE(games_max,0), COALESCE(clubs_max,0), COALESCE(current_games,0), COALESCE(current_clubs,0), COALESCE(point,0),
	//                COALESCE(reg_code,''), COALESCE(sale_code,''), COALESCE(card_type,0), COALESCE(token,''), COALESCE(device_type,0),
	//                COALESCE(reg_time,0),  COALESCE(last_login,0), COALESCE(is_online,0), COALESCE(room_id,0) from dtb_user_main `

	// *******************************
	if redis.GetRedisIsOpen() {
		baseinfo := new(UserBaseInfo)
		val, err := redis.GetRedisClient().HGet(redis.GS_USERBASE_INFO, strconv.Itoa(int(uid)))
		if err != nil {
			logger.Error("GetUserBaseInfo failed err=%v", err)
			return nil, err
		}
		err = json.Unmarshal([]byte(val), baseinfo)
		if err != nil {
			logger.Error("GetUserBaseInfo json failed err=%v", err)
			return nil, err
		}

		player := new(common.GamePlayer)
		player.UID = uid
		player.ConnLocker = new(sync.RWMutex)
		player.OutChannel = make(chan []byte, 32)
		player.OutDone = make(chan bool)
		player.LastAt = time.Now().Unix()
		return player, nil
	}
	// *******************************
	cmd := "select uuid from dtb_user_main where uuid = " + strconv.Itoa(uid)
	rows, err := m_game_db.Query(cmd)
	if rows != nil {
		defer rows.Close()
	}
	if err != nil {
		logger.Info("LoadPlayerFromDB Query error:%v cmd:%v", err, cmd)
		return nil, err
	}
	for rows.Next() {
		var id int
		err = rows.Scan(&id)
		if err != nil {
			logger.Notic("LoadPlayerFromDB scan error:%v", err)
			return nil, err
		}

		logger.Info("id:%v", id)

		player := new(common.GamePlayer)
		player.UID = uid
		player.ConnLocker = new(sync.RWMutex)
		player.OutChannel = make(chan []byte, 32)
		player.OutDone = make(chan bool)
		player.LastAt = time.Now().Unix()
		return player, nil
	}
	err = common.ErrorsNotFoundPlayerInMysql
	return nil, err
}

func UpdateToken(token string, uuid int) error {

	// *******************************
	if redis.GetRedisIsOpen() {

		baseinfo := new(UserDeviceInfo)
		val, err := redis.GetRedisClient().HGet(redis.GS_USERDEVICE_INFO, strconv.Itoa(uuid))
		if err != nil {
			logger.Error("UpdateToken failed err=%v", err)
			return err
		}
		err = json.Unmarshal([]byte(val), baseinfo)
		if err != nil {
			logger.Error("UpdateToken json failed err=%v", err)
			return err
		}

		baseinfo.Token = token

		newval, err := json.Marshal(baseinfo)
		if err != nil {
			logger.Error("UpdateToken err=%v", err)
			return err
		}

		err = redis.GetRedisClient().HSet(redis.GS_USERDEVICE_INFO, strconv.Itoa(int(uuid)), string(newval))

		if err != nil {
			logger.Error("UpdateToken err=%v", err)
			return err
		}
		return nil
	}
	// *******************************

	_, err := m_game_db.Exec("update dtb_user_deviceinfo set login_token= ? where uuid=?", token, uuid)
	if err != nil {
		logger.Info("UpdateToken error:%v", err)
		return err
	}

	return nil
}

func GetGameUrl(gameid int32) (string, error) {

	// *******************************
	if redis.GetRedisIsOpen() {
		val, err := redis.GetRedisClient().HGet(redis.WD_REDIS_GAME_LIST, strconv.Itoa(int(gameid)))
		if err != nil {
			logger.Error("UpdateToken failed err=%v", err)
			return "", err
		}

		return string(val), nil
	}
	// *******************************

	gameurl := ""
	row := m_game_db.QueryRow("select game_url from dtb_game_list where gameid = ?", gameid)

	err := row.Scan(&gameurl)

	if err != nil {
		logger.Info("GetGameUrl error:%v", err)
		return gameurl, err
	}

	return gameurl, nil
}
